package cn.funeralobjects.asms.web.controller;

import cn.funeralobjects.ams.web.api.ProductApiApi;
import cn.funeralobjects.asms.entity.ESmsSign;
import cn.funeralobjects.asms.model.SmsSign;
import cn.funeralobjects.asms.service.SmsSignService;
import cn.funeralobjects.asms.web.mapper.SmsSignMapper;
import cn.funeralobjects.asms.web.model.MSmsSign;
import cn.funeralobjects.asms.web.model.VSmsSign;
import cn.funeralobjects.common.service.EntityService;
import cn.funeralobjects.common.service.IdService;
import cn.funeralobjects.common.service.exception.LackDataException;
import cn.funeralobjects.common.service.exception.OperationException;
import cn.funeralobjects.common.web.controller.RestEntityController;
import cn.funeralobjects.common.web.controller.converter.VoMapper;
import cn.funeralobjects.utils.aliyun.core.AliyunClientFactory;
import cn.funeralobjects.utils.aliyun.sms.SmsAction;
import cn.funeralobjects.utils.aliyun.sms.model.QuerySmsSignData;
import cn.funeralobjects.utils.aliyun.sms.model.QuerySmsSignParam;
import cn.funeralobjects.web.api.SmsSignApi;
import com.aliyuncs.exceptions.ClientException;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

/**
 * Controller of SmsSign
 *
 * @author FuneralObjects
 * Create date: 2020/6/1 3:21 AM
 */
@RestController
@RequestMapping("/sms-sign")
public class SmsSignController implements SmsSignApi, RestEntityController<VSmsSign, ESmsSign, Integer> {

    @Resource
    private SmsSignMapper smsSignMapper;

    @Resource
    private SmsSignService smsSignService;

    @Resource
    private ProductApiApi productApiApi;

    @PostMapping
    @Override
    public Mono<VSmsSign> add(@RequestBody MSmsSign mSmsSign) {
        return Mono.just(mSmsSign.getProdResCode())
                .flatMap(prodResCode -> productApiApi.getExistsAccessKey(prodResCode, SmsAction.QUERY_SMS_SIGN.getAction(), SmsAction.QUERY_SMS_SIGN.getVersion()))
                .switchIfEmpty(Mono.error(new OperationException(String.format("The Action of SmsAction.QUERY_SMS_SIGN in ProductRes[%S] doesn't has any AccessKey!", mSmsSign.getProdResCode()))))
                .map(vAccessKey -> AliyunClientFactory
                        .builder().setAccessKeyId(vAccessKey.getAccessKeyId())
                        .setAccessKeySecret(vAccessKey.getAccessKeySecret())
                        .build(vAccessKey.getRegionId())
                        .buildClient(SmsAction.QUERY_SMS_SIGN)
                )
                .map(client -> {
                    QuerySmsSignData data;
                    try {
                        data = client.doAction(new QuerySmsSignParam(mSmsSign.getSignName())).getData();
                    } catch (ClientException e) {
                        throw new RuntimeException(e);
                    }
                    if (data == null) {
                        throw new LackDataException(String.format("Can't find sign[%s]", mSmsSign.getSignName()));
                    }
                    return this.toVo(smsSignService.add(
                            new SmsSign()
                                    .setCode(mSmsSign.getCode())
                                    .setCreateDate(data.getCreateDate())
                                    .setProdResCode(mSmsSign.getProdResCode())
                                    .setReason(data.getReason())
                                    .setSignName(data.getSignName())
                                    .setStatus(data.getSignStatus())
                            )
                    );
                });

    }

    @Override
    public EntityService<ESmsSign, Integer> entityService() {
        return smsSignService;
    }

    @Override
    public IdService<Integer> idService() {
        return smsSignService;
    }

    @Override
    public VoMapper<ESmsSign, VSmsSign> voMapper() {
        return smsSignMapper;
    }
}
